package ro.upt.ac.cstaicu.execution.junit;

import java.util.ArrayList;

import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;

import ro.upt.ac.cstaicu.execution.Executor;
import ro.upt.ac.cstaicu.execution.TestResult;
import ro.upt.ac.cstaicu.instrumentation.logging.GlobalLogger;
import ro.upt.ac.cstaicu.instrumentation.logging.PredicateCounterLogger;

/**
 * This class is a listener for the {@link JUnitCore} class used in the
 * {@link JunitFacade}. Each time an event related to test execution occurs the
 * listener is notified. It uses a the {@link GlobalLogger} to log the results.
 * 
 * @author Cristian-Alexandru STAICU
 * 
 */
public class JunitTestResultListener extends RunListener {

	/**
	 * A flag that is set when the testFailure method is called.
	 */
	private boolean wasFail = false;

	/**
	 * The name of the current class
	 */
	private String currentTestClass;
	/**
	 * The name of the current method
	 */
	private String currentTestMethod;

	/**
	 * A list with all the executed tests
	 */
	private ArrayList<TestResult> results = new ArrayList<TestResult>();

	@Override
	public void testRunStarted(Description description) throws Exception {
//		System.out.println(description);
		super.testRunStarted(description);
	}
	
	/**
	 * The {@link GlobalLogger} is announced that the current that has started.
	 * 
	 * @param description
	 *            info about the current test
	 */
	@Override
	public void testStarted(Description description) throws Exception {
//		System.out.println(description);
		// TODO use polymorphism/composition
		PredicateCounterLogger.getInstance().testStarted(
				description.getClassName(), description.getMethodName());
		currentTestClass = description.getClassName();
		currentTestMethod = description.getMethodName();
	}

	/**
	 * The {@link GlobalLogger} is announced that the current test has failed.
	 * The wasFail flag is set on true.
	 * 
	 * @param failure
	 *            - the cause of the test failure
	 */
	@Override
	public void testFailure(Failure failure) throws Exception {
		// TODO use polymorphism/composition
//		System.out.println("FAILURE" + failure.getTrace());
		TestResult res = new TestResult(currentTestClass, currentTestMethod,
//				Executor.TEST_FAILED, failure.getException().getClass().getSimpleName());
				Executor.TEST_FAILED, failure.getTrace());
		PredicateCounterLogger.getInstance().setResult(res);
		results.add(res);
		wasFail = true;
	}

	/**
	 * If the testFailure wasn't called it means that the current test was a
	 * success and the {@link GlobalLogger} is informed about this fact
	 * 
	 * @param description
	 *            - info about the current test (never used);
	 */
	@Override
	public void testFinished(Description description) throws Exception {
//		System.out.println("Test finished " + wasFail);
		if (!wasFail) {
			TestResult res = new TestResult(currentTestClass, currentTestMethod,
					Executor.TEST_PASSED, "");
			// TODO use polymorphism/composition
			PredicateCounterLogger.getInstance().setResult(res);
			results.add(res);
		}
		wasFail = false;
	}

	public ArrayList<TestResult> getResults() {
		return results;
	}

}
